<?php

    /**
     * @package      Modules
     * @subpackage   Base_Classes_Db
     *
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    abstract class DbBase extends Doctrine_Record
    {

    ////////////////////////////////////////////////////////////////////////////
    //                               Constants                                //
    ////////////////////////////////////////////////////////////////////////////

        const ENABLED  = 2;
        const DISABLED = 1;
        const TRASH    = 0;
        const DELETED  = -1;
        const ROOT     = -2;

    ////////////////////////////////////////////////////////////////////////////
    //                                 Methods                                //
    ////////////////////////////////////////////////////////////////////////////

		public function setTableDefinition()
		{
			$this->setTableName('db_base');
			$this->hasColumn('status', 'integer', 2, array('type' => 'integer', 'notnull' => true, 'default' => 1, 'length' => '2'));
			$this->setAttribute(Doctrine::ATTR_VALIDATE, true);

			$this->option('collate', 'utf8_unicode_ci');
			$this->option('charset', 'utf8');
		}

        public function setUp()
        {
            $timestampable0 = new Doctrine_Template_Timestampable(array('created' => array('name' => 'creation_date', 'type' => 'timestamp'), 'updated' => array('name' => 'last_modification_date', 'type' => 'timestamp')));
            $this->actAs($timestampable0);
        }

        /**
         * Enables the element
         *
         * @return      void
         */
        public function enable()
        {
            $this->_changeStatus(DbBase::ENABLED);
        }

        /**
         * Disables the element
         *
         * @return      void
         */
        public function disable()
        {
            $this->_changeStatus(DbBase::DISABLED);
        }

        /**
         * Moves the element in the trash
         *
         * @return      void
         */
        public function moveTrash()
        {
            if ($this->status == DbBase::ENABLED || $this->status == DbBase::DISABLED) {
                $this->_changeStatus(DbBase::TRASH);
            }
        }

        /**
         * Removes the element from trash
         *
         * @return      void
         */
        public function removeFromTrash($hardDelete = false)
        {
            if ($hardDelete) {
                parent::delete();
            } else {
                $this->_changeStatus(DbBase::DELETED);
            }
        }
        
        /**
         * Restore the element, which has to be in the corbeille
         *
         * @return      void
         */
        public function restore()
        {
            if ($this->status == DbBase::TRASH) {
                $this->_changeStatus(DbBase::DISABLED);
            }
        }

        /**
         * Moves the element up in the nested set
         *
         * @return      void
         */
        public function moveUp()
        {
            $node   = $this->getNode();
            $result = false;

            if ($node != false) {
                $nextNode   = $node->getPrevSibling();
                $result     = $node->moveAsPrevSiblingOf($nextNode);
            }

            return $result;
        }

        /**
         * Moves the element down in the nested set
         *
         * @return      void
         */
        public function moveDown()
        {
            $node   = $this->getNode();
            $result = false;

            if ($node != false) {
                $prevNode   = $node->getNextSibling();
                $result     = $node->moveAsNextSiblingOf($prevNode);
            }

            return $result;
        }

        /**
         * Returns if the element has a next element (only if nested set)
         *
         * @param       array $status
         * @return      boolean
         */
        public function hasNext($status = array())
        {
            $hasNext        = false;
            $node           = $this->getNode();

            if ($node !== false) {
                $sibling    = $node->getNextSibling();
                if ($sibling !== false) {
                    if (count($status) > 0) {
                        if (in_array($sibling->status, $status)) {
                            $hasNext    = true;
                        } else {
                            $hasNext    = false;
                        }
                    } else {
                        $hasNext    = true;
                    }
                }
            }

            return $hasNext;
        }

        /**
         * Returns if the element has a previous element (only if nested set)
         *
         * @param       array $status
         * @return      boolean
         */
        public function hasPrevious($status = array())
        {
            $hasPrevious    = false;
            $node           = $this->getNode();

            if ($node !== false) {
                $sibling    = $node->getPrevSibling();
                if ($sibling !== false) {
                    if (count($status) > 0) {
                        if (in_array($sibling->status, $status)) {
                            $hasPrevious    = true;
                        } else {
                            $hasPrevious    = false;
                        }
                    } else {
                        $hasPrevious    = true;
                    }
                }
            }

            return $hasPrevious;
        }

        /**
         * Change the status of the element
         *
         * @param   int $statut
         */
        private function _changeStatus($status)
        {
            $this->status = $status;
            $this->save();
        }

        /**
         * Redefinition of the toString
         *
         * @return string
         */
        public function __toString() {
            return $this->id;
        }

        /**
         * Updates the I18N slug field, if it is empty sets to the same value as reference field
         *
         * @param       string  $model
         * @param       string  $reference_field
         * @param       string  $slug_field
         * @return      void
         */
        protected function _updateI18nSlug($model, $reference_field, $slug_field)
        {
            if (empty($this->Translation[Core_Locale::getInstance()->getLocale()]->{$slug_field})) {
                $base_slug  = $this->Translation[Core_Locale::getInstance()->getLocale()]->{$reference_field};
            } else {
                $base_slug  = $this->Translation[Core_Locale::getInstance()->getLocale()]->{$slug_field};
            }

            $base_slug      = Doctrine_Inflector::urlize($base_slug);

            $this->Translation[Core_Locale::getInstance()->getLocale()]->{$slug_field}  = $this->_getUniqueI18nSlug($model, $slug_field, $base_slug);
        }

        /**
         * Returns the unique value of given field
         * If already exists, adds a counter at the end of the string
         *
         * @param       string  $model
         * @param       string  $field
         * @param       string  $value
         * @param       int     $counter
         * @return      string
         */
        private function _getUniqueI18nSlug($model, $field, $value, $counter = null)
        {
            if ($counter === null) {
                $new_value  = $value;
            } else {
                $new_value  = $value . '-' . $counter;
            }

            // Searches if the value exists
            $query          = Doctrine_Query::create()
                                    ->from($model . ' m')
                                    ->leftJoin('m.Translation t')
                                    ->where('t.' . $field . ' LIKE ?', $new_value)
                                    ->addWhere('t.lang = ?', Core_Locale::getInstance()->getLocale());

            if ($this->id !== null) {
                $query->addWhere('m.id != ?', $this->id);
            }

            $elements       = $query->count();

            // There is already an element with that URL
            if ($elements > 0) {
                // Adds a counter
                $counter    = intval($counter) + 1;

                // Gets the value with the counter
                $new_value  = $this->_getUniqueI18nSlug($model, $field, $value, $counter);
            }

            return $new_value;
        }

        /**
         * Returns the URL of an element's image's URL
         * If default is true, returns a default image URL
         *
         * @param       string  $module_name
         * @param       string  $field_name
         * @param       string  $element_id
         * @param       string  $extension
         * @param       boolean $default
         * @return      string
         */
        public static function getImageUrl($module_name, $field_name, $element_id, $extension, $default = false)
        {
            $file_name          = $element_id . '.' . $extension;
            $screenshot_path    = Core_IO_Path::combine(PROJECT_MEDIA_PATH, 'modules', 'videos', 'file_screenshot', $file_name);

            if (file_exists($screenshot_path)) {
                return 'project/media/modules/' . $module_name . '/' . $field_name . '/' . $file_name;
            } elseif ($default) {
                return '';
            } else {
                return null;
            }
        }
    }